home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / sox / pred.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  5KB  |  239 lines

  1.  
  2. /*
  3.  * July 5, 1991
  4.  * Copyright 1991 Lance Norskog And Sundry Contributors
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose.  This copyright notice must be maintained. 
  7.  * Lance Norskog And Sundry Contributors are not responsible for 
  8.  * the consequences of using this software.
  9.  */
  10.  
  11. /*
  12.  * Sound Tools prediction-correction compression effect file.
  13.  * Experiment with various simple equation systems.
  14.  * 
  15.  * This is not ready for prime time.  It's here for research purposes.
  16.  * Sox will hang if you run this as is.  Define D0 or D1, recompile,
  17.  * and try compressing the output with 'compress' and 'pack'.  
  18.  *
  19.  * Inspired by 2D PC gem in Graphics Gems II.
  20.  */
  21.  
  22. #include "st.h"
  23.  
  24. #define    D0    /* output difference between successive samples */
  25. /* #define    D1    /* guess by extending slope of last two samples */
  26. /* #define    D2     /* extend second derivate and guess signal turn */
  27. /* Autocorrelation isn't worth pursuing.  D2 should do an excellent job */
  28.  
  29. /* Private data for Prediction-Correction state machine */
  30. typedef struct predstuff {
  31.     int    direction;        /* 0 for compress, 1 for decompress */
  32.     int    first;            /* first time through? */
  33.     u_i    error;            /* average error output */
  34.     int    clipped;        /* # of clipped error values */
  35. #ifdef    D0 
  36.     long    in[1];            /* previous input sample */
  37. #endif
  38. #ifdef    D1
  39.     long    in[2];            /* previous input samples */
  40. #endif
  41. } *pred_t;
  42.  
  43. long pred_init(), pred_ict(), pred_next();
  44.  
  45. /*
  46.  * Process options
  47.  */
  48. pred_getopts(effp, n, argv) 
  49. eff_t effp;
  50. int n;
  51. char **argv;
  52. {
  53.     pred_t pred = (pred_t) effp->priv;
  54.  
  55.     if ((n != 1) || 
  56.             (strcmp(argv[0], "-c") && strcmp(argv[0], "-d")))
  57.         fail("Linp compression requires in or out options.");
  58.  
  59.     pred->direction = strcmp(argv[0], "-c");
  60. }
  61.  
  62. /*
  63.  * Start processing
  64.  */
  65. pred_start(effp)
  66. eff_t effp;
  67. {
  68.     pred_t pred = (pred_t) effp->priv;
  69.  
  70.     pred->error = 0;
  71.     pred->first = 1;
  72.     pred->clipped = 0;
  73. }
  74.  
  75. /*
  76.  * Process according to compression direction.
  77.  * Both loops use the same state machine, 
  78.  * but feed it from different streams.
  79.  */
  80. /*
  81.  * If first time, emit first two samples.
  82.  * Then,
  83.  */
  84.  
  85. pred_flow(effp, ibuf, obuf, isamp, osamp)
  86. eff_t effp;
  87. long *ibuf, *obuf;
  88. int *isamp, *osamp;
  89. {
  90.     int len, done;
  91.     pred_t pred = (pred_t) effp->priv;
  92.     register long predict, error;
  93.     
  94.     done = 0;
  95.     if (pred->first) {
  96.         done = pred_init(effp, ibuf, obuf);
  97.         ibuf += done;
  98.         obuf += done;
  99.         pred->first = 0;
  100.     }
  101.     len = ((*isamp > *osamp) ? *osamp : *isamp);
  102.     if (done > len)        /* it can't happen here */
  103.         fail("Prediction effect: not enough samples?");
  104.     if (pred->direction) {            /* decompress */
  105.         for(; done < len; done++) {
  106.             /* reconstitute sample from prediction and error */
  107.             predict = pred_ict(effp);
  108.             error = *ibuf;
  109.             pred_next(effp, predict + error);
  110.             pred->error = pred->error/2 + abs(error)/2;
  111.             *obuf++ = predict + error;
  112.             ibuf++;
  113.         }
  114.     } else {                /* compress */
  115.         for(; done < len; done++) {
  116.             /* generate sample from prediction and error */
  117.             predict = pred_ict(effp);
  118.             error = *ibuf - predict;
  119.             pred->error = pred->error/2 + abs(error)/2;
  120.             if (predict + error != *ibuf)
  121.                 pred->clipped++;
  122.             pred_next(effp, *ibuf);
  123.             ibuf++;
  124.             *obuf++ = error;
  125.         }
  126.     }
  127. }
  128.  
  129. /* 
  130.  * Linear Prediction state machine part A.
  131.  * 
  132.  * Initialize from buffer.  Return number of samples processed.
  133.  * It will be the same for input and output streams.
  134.  */
  135. long
  136. pred_init(effp, ibuf, obuf)
  137. eff_t effp;
  138. long *ibuf, *obuf;
  139. {
  140.     pred_t pred = (pred_t) effp->priv;
  141.  
  142.     /* 
  143.      * This is bogus!  
  144.      * Just pretend samples in negative time are 0, make a first few
  145.      * weird guesses.
  146.      */
  147. #ifdef    D0
  148.     /* same for compress and decompress */
  149.     pred->in[0] = *obuf++ = *ibuf++;
  150.     return 1;
  151. #endif
  152. #ifdef    D1
  153.     /* same for compress and decompress */
  154.     pred->in[0] = *obuf++ = *ibuf++;
  155.     pred->in[1] = *obuf++ = *ibuf++;
  156.     return 2;
  157. #endif
  158. }
  159.  
  160. /* 
  161.  * Linear Prediction state machine part B.
  162.  * 
  163.  * Emit a predicted sample.
  164.  */
  165. long
  166. pred_ict(effp)
  167. eff_t effp;
  168. {
  169.     pred_t pred = (pred_t) effp->priv;
  170.  
  171. #ifdef    D1
  172.     avg = (pred->in[0]/2 + pred->in[1]/2);
  173.     return pred->in[1] + (pred->in[1] - avg);
  174. #endif
  175. #ifdef    D0
  176.     /* Assume flat data */
  177.     return pred->in[0];
  178. #endif
  179. }
  180.  
  181. /* 
  182.  * Linear Prediction state machine, part C.
  183.  * 
  184.  * Process next sample.
  185.  */
  186. long
  187. pred_next(effp, samp)
  188. eff_t effp;
  189. long samp;
  190. {
  191.     pred_t pred = (pred_t) effp->priv;
  192.  
  193. #ifdef    D1
  194.     pred->in[0] = pred->in[1];
  195.     pred->in[1] = samp;
  196. #endif
  197. #ifdef    D0
  198.     /* Assume flat data */
  199.     pred->in[0] = samp;
  200. #endif
  201. }
  202.  
  203. /*
  204.  * Do anything required when you stop reading samples.  
  205.  * Don't close input file! 
  206.  */
  207. pred_stop(effp)
  208. eff_t effp;
  209. {
  210.     pred_t pred = (pred_t) effp->priv;
  211.     int error;
  212.     int size;
  213.  
  214.     /* XXX Or should it always be the input size? */
  215.     if (pred->direction)
  216.         size = effp->ininfo.size;
  217.     else
  218.         size = effp->outinfo.size;
  219.     switch(size) {
  220.         case WORD:
  221.             error = pred->error / ((long)1 << 16);
  222.             break;
  223.         case BYTE:
  224.             error = pred->error / ((long)1 << 24);
  225.             break;
  226.         default:
  227.             error = pred->error;
  228.             break;
  229.     }
  230.     /* nothing to do */
  231.     fprintf(stderr, "Prediction\n\tAverage Error outputs: %d\n", error);
  232.     fprintf(stderr, "\tClipped error outputs: %d\n", pred->clipped);
  233. }
  234.  
  235.  
  236.  
  237.  
  238.  
  239.